import * as fs from 'fs-extra';

import { SimulationModelHandler } from '../strategy/modelZipHandler';
import { TreeNode, DirectoryTreeReader } from '../../../service/directoryTree';
import { BaseResponese, SimulationModel } from '../type';
import { LocalModelHandler, RemoteModelHandler } from '../strategy/modelProcessStrategy';
import { DriverParseCommand, DriverParseOptions } from '$domain/model/driver';
import { logger, isZip, createTempDirectory, createTempFile, JsonFileUtility } from '$common';
import { agentConfig } from '../../agent/config';
export class SimulationModelService {

  constructor(private model: SimulationModel) { }

  async getModelDirectoryTrees() {
    let rootTreeNode: TreeNode;
    const modelFilePath = this.model.file;
    if (isZip(modelFilePath)) {
      rootTreeNode = await new DirectoryTreeReader().fromZip(modelFilePath);
    } else {
      rootTreeNode = await new DirectoryTreeReader().fromDirectory(modelFilePath);
    }
    return rootTreeNode;
  }

  public async unzipModelIfNecessary(unzipTo: string) {
    const modelZipHander = new SimulationModelHandler();

    if (this.model.type === 'local') {
      modelZipHander.setHandler(new LocalModelHandler());
    } else {
      modelZipHander.setHandler(new RemoteModelHandler());
    }
    return await modelZipHander.unzipFromTo(this.model.file, unzipTo);
  }

  async parseModelParam(product: string) {
    
    const simModelDir = await this.unzipModelIfNecessary(createTempDirectory());

    const outputFilePath = createTempFile('.json');

    const driverParseArgs: DriverParseOptions = {
      driverName: product,
      outputFilePath,
      modelDir: simModelDir,
      modelEntry: this.model.entry
    };

    const driverParseCommand = new DriverParseCommand(driverParseArgs);
    await driverParseCommand.execute();

    if (!fs.pathExistsSync(outputFilePath)) {
      throw new Error(`${outputFilePath} is not exist.`);
    }
    
    if (agentConfig.modelCleanup && this.model.type === 'remote' && fs.pathExistsSync(simModelDir)) {
      fs.remove(simModelDir)
        .then(() => logger.info(`delete tmp model dir: ${simModelDir}`))
        .catch(e => {
          setTimeout(() => {
            fs.removeSync(simModelDir);
            logger.info(`retry delete tmp model dir: ${simModelDir}`);
          }, 5000);
        });
    }

    return JsonFileUtility.deserializeFromFile<BaseResponese>(outputFilePath);
  }
}